//
//  WCWidgetPlugin.m
//  WebClipperDash
//
//  Created by Daniel Braun on 03/04/07.
//  Copyright 2007 Daniel Braun http://page-appart.net, http://braun.daniel.free.fr  All rights reserved.
//

#import <WebKit/WebKit.h>
#import "WCWidgetPlugin.h"

#import "WCWebLoader.h"
#import "WCWebExtractSet.h"
#import "WCExtractSetArray.h"

@implementation WCWidgetPlugin

- (id) initWithWebView:(WebView*)webView
{
	NSLog(@"WCWidgetPlugin/initWithWebView\n");
	self=[self init];
	return self;
}

- (void) loadEsets:(NSString *)p
{
	//NSLog(@"laod esets %@\n", p ? p : @"embedded");
	if (!p) {
		p=@"main.webExtract";
	}	
	p=[NSString stringWithFormat:@"%@/../%@", [[NSBundle bundleForClass:[self class]] bundlePath
		], p];
	NSLog(@"opening %@\n", p);
	if (!p) {
		NSLog(@"bad, main.webExtract %@ not found\n",p);
		return;
	}
	NSError *err=nil;
	NSData *data=[NSData dataWithContentsOfFile:p 
					    options:0
					      error:&err];
	if (!data) {
		char tmp[1024*2];
		NSLog(@"error reading file %@ : %@\n", p, err);
		NSLog(@"curdir %s\n", getcwd(tmp, sizeof(tmp)));
		return;
	}
	NSDictionary *info = [NSKeyedUnarchiver unarchiveObjectWithData:data];
	if (!info) {
		NSLog(@"unarchive failed\n");
		goto badfile;
	}
	[esets release];
	esets=[[WCExtractSetArray extractSetArrayFromSaveDictionnary:info]retain];
	if (!esets) {
		NSLog(@"no esets\n");
		goto badfile;
	}
	if ([esets count]<1) {
		NSLog(@"empty esets\n");
		goto badfile;
	}	
	unsigned int i, count = [esets count];
	for (i = 0; i < count-1; i++) {
		WCWebExtractSet * es = [esets objectAtIndex:i];
		[es setNextExtractSet:[esets objectAtIndex:i+1]];
	}
	
	return;
badfile:
	[esets release];
	esets=nil;
	NSLog(@"failed loading %@\n", p);
}

- (void) setDone:(BOOL)b
{
	if (b) NSLog(@"all loaded, got %d val : %@\n", [extracted count], [extracted allKeys]);
	allDone=b;
}

- (void) pageLoadedBy:(NSObject <WCWebLoadProtocol> *)ctrler private:(WCWebExtractSet*)wes
{
	//NSLog(@"page loaded\n");
	[self willChangeValueForKey:@"extractedArray"];
	NSDictionary *exv=[wes processExtractionWithController:ctrler];
	NSMutableDictionary *md=[NSMutableDictionary dictionaryWithCapacity:[exv count]];
	NSEnumerator *e=[exv keyEnumerator];
	NSString *k;
	while (k=[e nextObject]) {
		NSString *v;
		NSString *nk;
		v=[exv objectForKey:k];
		nk=[NSString stringWithFormat:@"%@.%@", [wes name], k];
		//NSLog(@"add key %@\n", nk);
		[md setObject:v forKey:nk];
	}
	if (!extracted) extracted=[md retain];
	else [extracted addEntriesFromDictionary:md];
	[self didChangeValueForKey:@"extractedArray"];
	NSDictionary *bodyv=[wes bodyVariables];
	wes=[wes nextExtractSet];
	if (wes) {
		NSString *content;
		NSURL *u;
		u=[wes actualUrlOrContent:&content];
		if (!u) {
			NSLog(@"hu? actualUrlOrContent returns nil\n");
			[self setDone:YES];
			return;
		}
		[loader setUrl:u delegateQuery:nil urlAccess:[wes urlaccess] bodyVariables:bodyv];

		if (content) {
			[loader loadHtml:content andPerform:@selector(pageLoadedBy:private:) 
				  target:self private:wes];
		} else  {
			[loader loadPageAndPerform:@selector(pageLoadedBy:private:) 
				    target:self private:wes];
		}
	} else {
		[self setDone:YES];
	}
	
}

- (void)  loadContent
{
	[loader release];
	loader=[[WCWebLoader alloc]init];
	WCWebExtractSet *wes=[esets objectAtIndex:0];
	[loader setUrl:[wes actualUrl] delegateQuery:nil urlAccess:[wes urlaccess] bodyVariables:nil];
	[self setDone:NO];
	[loader loadPageAndPerform:@selector(pageLoadedBy:private:) 
			    target:self private:wes];
}

		
- (BOOL) contentLoaded
{
	//NSLog(@"content loaded: %@\n", allDone ? @"YES":@"no");
	return allDone;
}
- (NSNumber *) allLoaded
{
	NSLog(@"allLoaded :content loaded: %@\n", allDone ? @"YES":@"no");
	if ([self contentLoaded]) {
		return [NSNumber numberWithInt:1];
	} else {
		return [NSNumber numberWithInt:0];
	}
}

- (NSDictionary *) extracts
{
	return extracted;
}
- (id) extractForKey:(NSString *) k
{
	id r=[extracted objectForKey:k];
	if (!r) {
		r=[esets userVariableValue:k withDictionary:extracted];
		if (!r) r=@"??";
	}
	if (0) NSLog(@"script fetch %@ : %@ (%@) (%@)\n", k, r, [r className],
	      ([r isKindOfClass:[NSString class]]) ? @"string": @"other");
	if ([r isKindOfClass:[NSString class]]) {
		r=[[[JString alloc] initWithObject:r]autorelease];
	} else if ([r isKindOfClass:[NSDate class]]) {
		r=[[[JString alloc] initWithObject:r]autorelease];
	} else if ([r isKindOfClass:[NSNumber class]]) {
		r=[[[JString alloc] initWithObject:r]autorelease];
	}
	return r;
}

- (void) activateHistory:(NSString *)appName
{
}

- (void) windowScriptObjectAvailable:(WindowScriptObject *) windowScriptObject
{
	//NSLog(@"windowScriptObjectAvailable\n");
	if (!esets) [self loadEsets:nil];
	if (esets && !loader) [self loadContent];
	[windowScriptObject setValue:self forKey:@"webExtract"];
}

- (void) load:(NSString *)s
{
	if (esets) return;
	NSLog(@"loadinfg %@\n", s);
	[self loadEsets:s];
	if (esets && !loader) [self loadContent];
}




+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
{
	//NSLog(@"isSelectorExcludedFromWebScript\n");
	return NO;
}

@end


@implementation JString
// for widget will send shortString to date ragne - but date range may  not be extracter
- (id) initWithObject:(id)_s
{
	self = [super init];
	if (self != nil) {
		//NSLog(@"JString init\n");
		obj=[_s retain];
	}
	return self;
}
- (void) dealloc {
	[obj release];
	[super dealloc];
}

- (NSString *) string
{
	return [obj description];
}

- (NSString *) shortString
{
	if ([obj respondsToSelector:@selector(shortString)]) return [obj shortString];
	if ([obj isKindOfClass:[NSNumber class]]) {
		return [NSString stringWithFormat:@"%0.2f", [obj doubleValue]];
	}
	NSString *s=[obj description];
	if ([s length]>15) s=[s substringToIndex:15];
	return s;
}
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
{
	NSLog(@"JString / isSelectorExcludedFromWebScript\n");
	if (aSelector==@selector(shortString)) return NO;
	if (aSelector==@selector(string)) return NO;
	return YES;
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
	if ([obj respondsToSelector:[anInvocation selector]]) {
		[anInvocation invokeWithTarget:obj];
	} else {
		[super forwardInvocation:anInvocation];
	}
}


- (BOOL) respondsToSelector:(SEL)aSelector
{
	if ( [super respondsToSelector:aSelector] )
		return YES;
	else if ([obj respondsToSelector:aSelector]) {
		return YES;
	}
	return NO;
}

- (NSString *) description
{
	NSLog(@"descr for %@\n", obj);
	return [obj description];
}
@end
